Introduction
This is a MCP23017-based IO expansion board that provides 16 additional IO ports for your microcontroller. It can be set up for 8 different addresses, which means that 8 modules can be connected through two IIC buses to achieve up to 128 IO extensions. This module is an excellent solution to the insufficient IO problem in applications like robots and interactive media.
This IO expansion board has 2 groups of IO pins: GPIOA and GPIOB. Each group has 8 independent IOs and each of them can be arbitrarily configured as input or output, and a pull-up input (connect to 100KΩ pull-up), interrupt and so on. Besides that, the module has 2 interrupt signal pins IA and IB which are used for detecting the interruption in the ports GPIOA and CPIOB respectively. When an interrupt occurs on one of the pin in CPIOA or GPIOB, the pin IA or IB will produce a High-level signal correspondingly.
Applications
- Robots
- Interactive Media
- Light Cube
Specification
- Power Supply: 3.3V-5.5V
- IIC Address: 0x20~0x27
- Digital IO/Input/Output: PA0-PA7, PB0-PB7
- IO Driving Current: 20mA
- Signal Interrupt Pin: IA, IB
- Dimension: 44x32mm / 1.73x1.26"
Board Overview
Num | Name | Description |
---|---|---|
1 | +/VCC | Positive |
2 | -/GND | Negative |
3 | C | IIC Clock Line |
4 | D | IIC Data Line |
5 | RST | Reset Pin |
6 | IA | GPIOA Interrupt Detection Pin |
7 | IB | GPIOB Interrupt Detection Pin |
8 | PWR | Power Indicator |
9 | A0/A1/A2 | IIC Address Switch |
Digital IO Port Table
CPIOA | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|---|---|---|
PA0 | PA1 | PA2 | PA3 | PA4 | PA5 | PA6 | PA7 | |
CPIOB | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
PB0 | PB1 | PB2 | PB3 | PB4 | PB5 | PB6 | PB7 |
Each digital pin in the table can be arbitrarily configured as input or output, and a pull-up input, interrupt and so on.
Tutorial
Requirements
- Hardware
- DFRduino UNO R3 (or similar) x 1
- MCP23017 IIC to 16 Digital IO Expansion Module x1
- Buttons
- LED Modules
- Software
- Arduino IDE
- Download and install the MCP23017 Library (About how to install the library?)
API Function List
/**
* @brief Set the pin mode to input, output or pull-up input (internal 100KΩ pull-up resistor)
* @param pin Pin number, it could be all enumeration values (eGPA0-eGPB7/ 0-15) included in ePin_t.
* @param mode Mode, it can be set to Input, Output, Pull-up Input (internal 100KΩ pull-up resistor)
* @return Return 0 if the setting is successful, otherwise return non-zero.
*/
int pinMode(ePin_t pin, uint8_t mode);
/**
* @brief Write digtial pin. The pin needs to be set to output mode before writing.
* @param pin Pin number, it could be all enumeration values (eGPA0-eGPB7/ 0-15) inlcuded in ePin_t.
* @param level High level 1 or Low level 0
* @return Return 0 if the writing is successful, otherwise return non-zero.
*/
int digitalWrite(ePin_t pin, uint8_t level);
/**
* @brief Read digital pin. The pin needs to be set to input mode before reading.
* @param pin Pin number, it could be all enumeration values (eGPA0-eGPB7/ 0-15) included in ePin_t.
* @return Return High or Low
*/
int digitalRead(ePin_t pin);
/**
* @brief Set a pin to interrupt mode
* @param pin Pin number, it could be all enumeration values (eGPA0-eGPB7/ 0-15) included in ePin_t.
* @param mode Interrupt mode: all enumeration values included in eInterruptMode_t.
* @param cb Interrupt service function, needs to be defined and transferred parameter by users. Prototype: void func(int)
*/
void pinModeInterrupt(ePin_t pin, eInterruptMode_t mode, MCP23017_INT_CB cb);
/**
* @brief Poll if an interrupt occurs on a port group.
* @param group Port group, it could be all enumeration values included in eGPIOGroup_t, GPIO GroupA(eGPIOA),
* @n GPIO GroupB(eGPIOB) GroupA+B (eGPIOALL).
* @n When setting to eGPIOA,poll if an interrupt occurs on the port group A.
* @n When setting to eGPIOB, poll if an interrupt occurs on the port group B.
* @n When setting to eGPIOALL, poll if an interrupt occurs on the port group A+B
* @n None, poll if an interrupt occurs on the all ports of group A and B by default.
*/
void pollInterrupts(eGPIOGroup_t group=eGPIOALL);
/**
* @brief Convert pin into string description
* @param pin Pin number, it could be all enumeration values (eGPA0-eGPB7/ 0-15) inlcuded in ePin_t.
* @return Return pin description string
* @n such as "eGPA0" "eGPA1" "eGPA2" "eGPA3" "eGPA4" "eGPA5" "eGPA6" "eGPA7"
* @n "eGPB0" "eGPB1" "eGPB2" "eGPB3" "eGPB4" "eGPB5" "eGPB6" "eGPB7"
* @n "eGPA" "eGPB"
*/
String pinDescription(ePin_t pin);
/**
* @brief Convert pin into string description
* @param pin Pin number, range 0~15
* @return Return pin description string
* @n such as "eGPA0" "eGPA1" "eGPA2" "eGPA3" "eGPA4" "eGPA5" "eGPA6" "eGPA7"
* @n "eGPB0" "eGPB1" "eGPB2" "eGPB3" "eGPB4" "eGPB5" "eGPB6" "eGPB7"
* @n "eGPA" "eGPB"
*/
String pinDescription(int pin);
The Relation Between DIP and IIC Address
A2 | A1 | A0 | IIC Address |
---|---|---|---|
0 | 0 | 0 | 0x20 |
0 | 0 | 1 | 0x21 |
0 | 1 | 0 | 0x22 |
0 | 1 | 1 | 0x23 |
1 | 0 | 0 | 0x24 |
1 | 0 | 1 | 0x25 |
1 | 1 | 0 | 0x26 |
1 | 1 | 1 | 0x27(Default) |
Connection Diagram
Sample Code 1- Button Input
Set the pin PA0 of the board to input mode, connect it with a button. When the button is pressed, serial print the string "Button press!".
/*!
* @file buttonInput.ino
* @brief Connect a button to the IO expansion board, set a pin of the board(eg: eGPA0) to input mode to detect the button status.
* @n Experiment phenomenon: connect a button on a pin of the IO board(eg:eGPA0), detect the level of the pin and print out
* @n the button status on serial port.
*
* @copyright Copyright (c) 2010 DFRobot Co.Ltd (https://www.dfrobot.com)
* @licence The MIT License (MIT)
* @author [Arya](xue.peng@dfrobot.com)
* @version V1.0
* @date 2019-07-18
* @get from https://www.dfrobot.com
* @url https://github.com/DFRobot/DFRobot_MCP23017
*/
#include <DFRobot_MCP23017.h>
/*DFRobot_MCP23017 constructor
*Parameter&wire Wire
*Parameter addr I2C address can be select from 0x20~0x27; the relationship of DIP switch(A2, A1, A0) and I2C address(0x27) is
*shown below:
* 0 0 1 0 | 0 A2 A1 A0
0 0 1 0 | 0 1 1 1 0x27
0 0 1 0 | 0 1 1 0 0x26
0 0 1 0 | 0 1 0 1 0x25
0 0 1 0 | 0 1 0 0 0x24
0 0 1 0 | 0 0 1 1 0x23
0 0 1 0 | 0 0 1 0 0x22
0 0 1 0 | 0 0 0 1 0x21
0 0 1 0 | 0 0 0 0 0x20
*/
DFRobot_MCP23017 mcp(Wire, /*addr =*/0x27);//constructor, change the Level of A2, A1, A0 via DIP switch to revise the I2C address within 0x20~0x27.
//DFRobot_MCP23017 mcp;//use default parameter, Wire 0x27(default I2C address)
//Prepare: connect a button to a digital pin of the IO expansion board(eg: eGPA0)
void setup() {
Serial.begin(115200);
/*wait for the chip to be initialized completely, and then exit*/
while(mcp.begin() != 0){
Serial.println("Initialization of the chip failed, please confirm that the chip connection is correct!");
delay(1000);
}
/*pinMode function is used to set the pin mode of module
Parameter pin, the available parameter is shown below:
eGPA0 eGPA1 eGPA2 eGPA3 eGPA4 eGPA5 eGPA6 eGPA7 eGPA
0 1 2 3 4 5 6 7
eGPB0 eGPB1 eGPB2 eGPB3 eGPB4 eGPB5 eGPB6 eGPB7 eGPB
8 9 10 11 12 13 14 15
Parameter mode, can be set to: INPUT, OUTPUT, INPUT_PULLUP(internal 100KΩ pull-up resistor)
*/
mcp.pinMode(/*pin = */mcp.eGPA0, /*mode = */INPUT);
/*Set all Group GPIOA pins to input*/
//mcp.pinMode(/*pin = */mcp.eGPA, /*mode = */INPUT);
}
void loop() {
/*digitalRead function is used to read the Level of a digital pin. The pin needs to be set to input mode before using this function.
Parameter pin, the available parameter is shown below:
eGPA0 eGPA1 eGPA2 eGPA3 eGPA4 eGPA5 eGPA6 eGPA7 eGPA
0 1 2 3 4 5 6 7
eGPB0 eGPB1 eGPB2 eGPB3 eGPB4 eGPB5 eGPB6 eGPB7 eGPB
8 9 10 11 12 13 14 15
*/
uint8_t value = mcp.digitalRead(/*pin = */mcp.eGPA0);
/*Read level of Group GPIOA pins*/
//value = mcp.digitalRead(/*pin = */mcp.eGPA);
if(value){
Serial.println("Button press!");
delay(200);
}else{
//Serial.println("Button release!");
}
}
- Expected Results When the button is pressed, print the "Button press" on the serial port.
Sample Code 2- Pin Output
Set the pin PA7 of the board to output mode, connect it with an LED, and change the LED state in one minute.
/*!
* @file ledOutput.ino
* @brief Set a pin of IO expansion board(eg:eGPA7) to output mode, and output High/Low.
* @n Experiment phenomenon: the LED connected to the pin of IO board(eg:eGPA7) repeatedly lights up for 1s and turns off 1s.
*
* @copyright Copyright (c) 2010 DFRobot Co.Ltd (https://www.dfrobot.com)
* @licence The MIT License (MIT)
* @author [Arya](xue.peng@dfrobot.com)
* @version V1.0
* @eGPAte 2019-07-18
* @get from https://www.dfrobot.com
* @url https://github.com/DFRobot/DFRobot_MCP23017
*/
#include <DFRobot_MCP23017.h>
/*DFRobot_MCP23017 Constructor
*Parameter &wire Wire
*Parameter addr I2C address can be selected from 0x20~0x27, the relationship of DIP switch (A2,A1,A0) and I2C address (0x27)is shown below:
* 0 0 1 0 | 0 A2 A1 A0
0 0 1 0 | 0 1 1 1 0x27
0 0 1 0 | 0 1 1 0 0x26
0 0 1 0 | 0 1 0 1 0x25
0 0 1 0 | 0 1 0 0 0x24
0 0 1 0 | 0 0 1 1 0x23
0 0 1 0 | 0 0 1 0 0x22
0 0 1 0 | 0 0 0 1 0x21
0 0 1 0 | 0 0 0 0 0x20
*/
DFRobot_MCP23017 mcp(Wire, /*addr =*/0x27);//constructor, change the Level of A2, A1, A0 via DIP switch to revise I2C address within 0x20~0x27
//DFRobot_MCP23017 mcp;//use default parameter, Wire 0x27(default I2C address)
//Prepare: connect the LED to a digital pin of IO expansion board(eg:eGPA7)
void setup(void)
{
Serial.begin(115200);
/*wait for the chip to be initialized completely, and then exit*/
while(mcp.begin() != 0){
Serial.println("Initialization of the chip failed, please confirm that the chip connection is correct!");
delay(1000);
}
/*pinMode function is used to set the pin mode of the module
Parameter pin, the available parameter is shown below:
eGPA0 eGPA1 eGPA2 eGPA3 eGPA4 eGPA5 eGPA6 eGPA7 eGPA
0 1 2 3 4 5 6 7
eGPB0 eGPB1 eGPB2 eGPB3 eGPB4 eGPB5 eGPB6 eGPB7 eGPB
8 9 10 11 12 13 14 15
Parameter mode, can be set to: INPUT, OUTPUT, INPUT_PULLUP mode (internal 100KΩ pull-up resistor)
*/
mcp.pinMode(/*pin = */mcp.eGPA7, /*mode = */OUTPUT);
/*Set all Group GPIOA pins to output*/
//mcp.pinMode(/*pin = */mcp.eGPA, /*mode = */OUTPUT);
}
void loop(void)
{
Serial.println("Pin output high level!");
/*digitalWrite function is used to make the pin output HIGH or LOW. The pin needs to be set to output mode before using this function.
Designate a pin on the IO expansion board; parameter pin, the available parameter is shown below:
eGPA0 eGPA1 eGPA2 eGPA3 eGPA4 eGPA5 eGPA6 eGPA7 eGPA
0 1 2 3 4 5 6 7
eGPB0 eGPB1 eGPB2 eGPB3 eGPB4 eGPB5 eGPB6 eGPB7 eGPB
8 9 10 11 12 13 14 15
*/
mcp.digitalWrite(/*pin = */mcp.eGPA7, /*level = */HIGH);
/*Set GPIOIA0-GPIOIA3 to low and GPIOIA4-GPIOIA7 to high*/
//mcp.digitalWrite(/*pin = */mcp.eGPA, /*Port Value = */0xF0);
delay(1000);
Serial.println("Pin output low level!");
mcp.digitalWrite(/*pin = */mcp.eGPA7, /*level = */LOW);
/*Set GPIOIA0-GPIOIA3 to high and GPIOIA4-GPIOIA7 to low*/
//mcp.digitalWrite(/*pin = */mcp.eGPA, /*Port Value = */0x0F);
delay(1000);
}
- Expected Results
The LED connected with pin PA7 changes the state in one minute, serial print the Level output from Pin PA7.
Sample Code- Interrupt Polling
Set the IO pins of the board to interrupt mode, such as eChangeLevel, eFalling, eRising, eHighLevel, eLowLevel. Set PA0, PA1, PB6, PB7 to eChangeLevel, eFalling, eRising, eHighLevel respectively, poll and serial print the pins where interrupt happened.
/*!
* @file pollInterrupt.ino
* @brief Set a pin of IO expansion board to interrupt mode, poll if there is an interrupt occurring on the pins of the port.
* @n Experiment phenomenon: poll if there is an interrupt occurring on the port group(A, B, A+B), if there is, serial print the pin which is interrupted.
*
* @copyright Copyright (c) 2010 DFRobot Co.Ltd (https://www.dfrobot.com)
* @licence The MIT License (MIT)
* @author [Arya](xue.peng@dfrobot.com)
* @version V1.0
* @date 2019-07-18
* @get from https://www.dfrobot.com
* @url https://github.com/DFRobot/DFRobot_MCP23017
*/
#include <DFRobot_MCP23017.h>
DFRobot_MCP23017 mcp(Wire, 0x27);//constructor, change the Level of A2, A1, A0 via DIP switch to revise I2C address within 0x20~0x27.
//DFRobot_MCP23017 mcp;//use default parameter, Wire 0x27(default I2C address)
/*Interrupt service function, prototype void func(int index), index: the number of the pin that is interrupted*/
void func(int index){
String description = mcp.pinDescription(/*pin = */index);
Serial.print(description);
Serial.println(" Interruption occurs!");
}
void setup() {
Serial.begin(115200);
/*wait for the chip to be initialized completely, and then exit*/
while(mcp.begin() != 0){
Serial.println("Initialization of the chip failed, please confirm that the chip connection is correct!");
delay(1000);
}
/*Parameter mode, the available is shown below:
eLowLevel eHighLevel eRising eFalling eChangeLevel
Low-level interrupt High-level interrupt Rising-edge interrupt Falling-edge interrupt Double-edge interrupts
Parameter cb Interrupt service function(with parameter)
Prototype void func(int)
*/
mcp.pinModeInterrupt(/*p = */mcp.eGPA0, /*mode = */mcp.eChangeLevel, /*cb = */func);//digital pin0(eGPA0), double edge interrupt, generate an interrupt when the status of pin0 changes, INTA output High level.
mcp.pinModeInterrupt(/*p = */mcp.eGPA1, /*mode = */mcp.eFalling, /*cb = */func);//digital pin1(eGPA1), falling edge interrupt, generate an interrupt when the status of pin 1 changes from High to Low, INTA output High level.
mcp.pinModeInterrupt(/*p = */mcp.eGPB7, /*mode = */mcp.eRising, /*cb = */func);//digital pin15(eGPB7), rising edge interrupt, generate an interrupt when the status of pin15 changes from Low to High, INTB output High level.
mcp.pinModeInterrupt(/*p = */mcp.eGPB6, /*mode = */mcp.eHighLevel, /*cb = */func);//digital pin14(eGPB6), high level interrupt, generate an interrupt when the pin 14 is in high level, INTB output High level.
}
void loop() {
/*pollInterrupts function is used to poll if an interrupt occurs on a port group
Parameter group, the available parameter is shown below: (default: eGPIOALL)
eGPIOA eGPIOB eGPIOALL
Port Group A Port Group B Port Group A+B
*/
mcp.pollInterrupts();
// delay(1000);
}
- Expected Results
Press the button connected with PA0, PA1, PB6, PB7 to trigger interrupt, and serial print the pins where interrupt happened.
Sample Code 4- IO Interrupt
Combine the pin INTA and INTB of the expansion board and the external interrupt of UNO to realize IO interrupt. Before downloading the following sample code, connect the IA and IB of the expansion board to UNO digital pin 2(external interrupt 0) and pin 3(external interrupt 1). Set the pin PA0 to eHighLevel interrupt, PB7 to double edge interrupt and connect buttons with them. Set UNO external interrupts to rising edge interrupt. Execute the related interrupt service function when an interrupt occurs.
For other microcontroller, check the interrupt pin at the table in the sample code below.
/*!
* @file ioInterrupt.ino
* @brief IO interrupt, set a pin of a port group(A or B) IO to interrupt mode. When an interrupt occurs on the related port group, pin INTA(group A) or INTB(group B) will output a High level.
* INTA and INTB are used to detect if an interrupt occurs on the pin of port eGPA and eGPB respectively; connect pin INTA and INTB to main-controller's external interrupt 0 and 1 respectively.
* @n Experiment phenomenon: when the signal change of pin INTA or INTB is detected by main-board, the related interrupt service function will be executed to print out which pin was interrupted on serial port.
*
* @copyright Copyright (c) 2010 DFRobot Co.Ltd (https://www.dfrobot.com)
* @licence The MIT License (MIT)
* @author [Arya](xue.peng@dfrobot.com)
* @version V1.0
* @eGPAte 2019-07-18
* @get from https://www.dfrobot.com
* @url https://github.com/DFRobot/DFRobot_MCP23017
*/
#include <DFRobot_MCP23017.h>
DFRobot_MCP23017 mcp(Wire, /*addr =*/0x27);//constructor, change the Level of A2, A1, A0 via DIP switch to revise I2C address within 0x20~0x27.
//DFRobot_MCP23017 mcp;//use default parameter, Wire 0x27(default I2C address)
//Connect 2 buttons to IO expansion board, one to a pin of port eGPA(eg: eGPA0), the other to a pin of port eGPB(eg: eGPB0)
//Connect INTA to the external interrupt pin0 of UNO, INTB to external interrupt pin1 of UNO.
bool intFlagA = false;//INTA interrupt sign
bool intFlagB = false;//INTB interrupt sign
/*Interrupt service function, prototype void func(int index), index represents the pin which is interrupted*/
void gpa0CB(int index){
String description = mcp.pinDescription(index);
Serial.print(description);Serial.println(" Interruption occurs!");
}
void gpb7CB(int index){
String description = mcp.pinDescription(index);
Serial.print(description);Serial.println(" Interruption occurs!");
}
void setup() {
Serial.begin(115200);
#ifdef ARDUINO_ARCH_MPYTHON
pinMode(P0, INPUT);//use mPython external interrupt, connect INTA to pin 0 of mPython.
pinMode(P1, INPUT);//use mPython external interrupt, connect INTB to pin 1 of mPython.
#else
pinMode(2, INPUT);//use UNO external interrupt 0
pinMode(3, INPUT);//use UNO external interrupt 1
#endif
/*wait for the chip to be initialized completely, and then exit*/
while(mcp.begin() != 0){
Serial.println("Initialization of the chip failed, please confirm that the chip connection is correct!");
delay(1000);
}
/*Parameter mode, the available parameter is shown below:
eLowLevel eHighLevel eRising eFalling eChangeLevel
Low-level interrupt High-level interrupt Rising edge interrupt Falling edge interrupt Double edge interrupts
Parameter cb interrupt service function(with parameter)
Prototype void func(int)
*/
mcp.pinModeInterrupt(/*pin = */mcp.eGPA0, /*mode = */mcp.eHighLevel, /*cb = */gpa0CB);//digital pin 0(eGPA0), interrupt in High level. Generate an interrupt when pin 0 is in High level state.INTA output High level.
mcp.pinModeInterrupt(/*pin = */mcp.eGPB7, /*mode = */mcp.eChangeLevel, /*cb = */gpb7CB);//digital pin 15(eGPB7), double edge interrupts. Generate an interrupt when the status of Pin 15 changes. INTB output High level.
#ifdef ARDUINO_ARCH_MPYTHON //
/* mPython Interrupt Pin vs Interrupt NO
* -------------------------------------------------------------------------------------
* | | DigitalPin | P0~P20 can be used as external interrupt|
* | mPython |--------------------------------------------------------------|
* | | Interrupt No | use digitalPinToInterrupt(Pn) to query interrupt number |
* |-----------------------------------------------------------------------------------|
*/
attachInterrupt(digitalPinToInterrupt(P0)/*query Interrupt NO of P0*/,notifyA,RISING);//Enable the external interrupt of mPython P0; rising edge trigger; connect INTA to P0
attachInterrupt(digitalPinToInterrupt(P1)/*query Interrupt NO of P1*/,notifyB,RISING);//Enable the external interrupt of mPython P1; rising edge trigger; connect INTB to P1
#else
/* Main-board of AVR series Interrupt Pin vs Interrupt NO
* ---------------------------------------------------------------------------------------
* | | DigitalPin | 2 | 3 | |
* | Uno, Nano, Mini, other 328-based |--------------------------------------------|
* | | Interrupt No | 0 | 1 | |
* |-------------------------------------------------------------------------------------|
* | | Pin | 2 | 3 | 21 | 20 | 19 | 18 |
* | Mega2560 |--------------------------------------------|
* | | Interrupt No | 0 | 1 | 2 | 3 | 4 | 5 |
* |-------------------------------------------------------------------------------------|
* | | Pin | 3 | 2 | 0 | 1 | 7 | |
* | Leonardo, other 32u4-based |--------------------------------------------|
* | | Interrupt No | 0 | 1 | 2 | 3 | 4 | |
* |--------------------------------------------------------------------------------------
*/
/* microbit Interrupt Pin vs Interrupt NO
* ---------------------------------------------------------------------------------------------------------------
* | | DigitalPin | P0~P20 can be used as external interrupt |
* | microbit |---------------------------------------------------------|
* |(when used as external interrupt, do not need to set it to input mode via pinMode) | Interrupt No | Interrupt NO is pin value, for instance, the Interrupt NO of P0 is 0, P1 is 1. |
* |-------------------------------------------------------------------------------------------------------------|
*/
attachInterrupt(/*Interrupt NO*/0,notifyA,RISING);//Enable external interrupt 0, connect INTA to the main-controller's digital pin: UNO(2),Mega2560(2),Leonardo(3),microbit(P0)
attachInterrupt(/*Interrupt NO*/1,notifyB,RISING);//Enable external interrupt 1, connect INTB to the main-controller's digital pin: UNO(3),Mega2560(3),Leonardo(2),microbit(P1)
#endif
}
/*Interrupt service function*/
void notifyA(){
intFlagA = true;
}
void notifyB(){
intFlagB = true;
}
void loop() {
if(intFlagA){
intFlagA = false;
/*pollInterrupts function is used to poll if an interrupt occurs on a port group
parameter group, the available parameter is shown below: (default value: eGPIOALL):
eGPIOA eGPIOB eGPIOALL
Port groupA Port groupB Port groupA+B
*/
mcp.pollInterrupts(/*group = */mcp.eGPIOA);
}
if(intFlagB){
intFlagB = false;
mcp.pollInterrupts(/*group = */mcp.eGPIOB);
}
}
- Expected Results
Press the button on PAO or PB7, the following result will be printed on the serial port.
Cascade Connection
FAQ
For any questions, advice or cool ideas to share, please visit the DFRobot Forum